﻿#include <QHelpEvent>
#include <QAbstractItemView>
#include <QHeaderView>
#include <QTreeView>
#include <QTableView>
#include <QToolTip>

#include  "tool_tipper.h"

#if _MSC_VER >= 1600
#pragma execution_character_set("utf-8")
#endif


ToolTipper::ToolTipper(QObject* parent) :
	QObject(parent)
{
}

bool ToolTipper::eventFilter(QObject* obj, QEvent* event)
{
	if (event->type() == QEvent::ToolTip)
	{
		QAbstractItemView* view = qobject_cast<QAbstractItemView*>(obj->parent());
		if (!view)
		{
			return  false;
		}

		QHeaderView* headerView = qobject_cast<QHeaderView*>(view);
		if (headerView)
		{
			return headerViewEventFilter(obj, event);
		}

		QHelpEvent* helpEvent = static_cast<QHelpEvent*>(event);
		QPoint pos = helpEvent->pos();
		QModelIndex index = view->indexAt(pos);
		if (!index.isValid())
		{
			return  false;
		}

		QString itemText = view->model()->data(index).toString();

		// 图标处理
		QSize iconSize(0, 0);
		QIcon icon = view->model()->data(index, Qt::DecorationRole).value<QIcon>();
		if (!icon.isNull())
		{
			QList<QSize> listSize = icon.availableSizes();
			if (listSize.size() > 0)
			{
				iconSize.setWidth(listSize.at(0).width());
				iconSize.setHeight(listSize.at(0).height());
			}
		}

		// 计算列头高度
		int headerHeight = 0;
		int headerWidth = 0;
		QTreeView* treeView = qobject_cast<QTreeView*>(view);
		if (treeView)
		{
			headerHeight = treeView->header()->height();
		}
		else
		{
			QTableView* tableView = qobject_cast<QTableView*>(view);
			if (tableView)
			{
				headerHeight = tableView->horizontalHeader()->height();
				headerWidth = tableView->verticalHeader()->width();
			}
		}

		// 文本边距
		const  int textMargin = view->style()->pixelMetric(QStyle::PM_FocusFrameHMargin) + 1;
		const  int iconMargin = iconSize.width() > 0 ? (view->style()->pixelMetric(QStyle::PM_FocusFrameHMargin) + 1) : 0;
		QRect rect = view->visualRect(index);
		QRect textRect = rect.adjusted(textMargin + iconSize.width() + iconMargin * 2, 0, -textMargin, 0);  //实际可用矩形

		QFontMetrics fm(view->font());
		int flags = view->model()->data(index, Qt::TextAlignmentRole).toInt();
		QSize itemTextSize = fm.boundingRect(textRect, flags | Qt::TextLongestVariant | Qt::TextWordWrap, itemText).size();

		if ((itemTextSize.width() > textRect.width() || itemTextSize.height() > textRect.height()) && !itemText.isEmpty())
		{
			// 指定tip的限定矩形
			rect.adjust(headerWidth, headerHeight, headerWidth, headerHeight);
			QToolTip::showText(helpEvent->globalPos(), itemText, view, rect);
		}
		else
		{
			QToolTip::hideText();
		}
		return  true;
	}

	return  false;
}

bool ToolTipper::headerViewEventFilter(QObject* obj, QEvent* event)
{
	if (event->type() == QEvent::ToolTip)
	{
		QHeaderView* headerView = qobject_cast<QHeaderView*>(obj->parent());
		if (!headerView)
		{
			return  false;
		}

		QHelpEvent* helpEvent = static_cast<QHelpEvent*>(event);
		QPoint pos = helpEvent->pos();
		int index = headerView->logicalIndexAt(pos);
		if (index < 0)
		{
			return  false;
		}

		QString itemText = headerView->model()->headerData(index, headerView->orientation()).toString();
		const  int textMargin = headerView->style()->pixelMetric(QStyle::PM_FocusFrameHMargin) + 1;
		int rectWidth = headerView->sectionSize(index) - textMargin * 2;
		int rectHeight = headerView->sizeHint().height();

		QFontMetrics fm(headerView->font());
		int flag = headerView->model()->headerData(index, headerView->orientation(), Qt::TextAlignmentRole).toInt();
		QSize itemTextSize = fm.size(flag, itemText);
		if ((itemTextSize.width() > rectWidth || itemTextSize.height() > rectHeight) && !itemText.isEmpty())
		{
			QToolTip::showText(helpEvent->globalPos(), itemText, headerView);
		}
		else
		{
			QToolTip::hideText();
		}
		return  true;
	}

	return  false;
}

